// 
//   Copyright © 2009 Jiří Zárevúcky <zarevucky.jiri@gmail.com>
//  
//   This program is free software: you can redistribute it and/or modify
//   it under the terms of the GNU Affero General Public License as
//   published by the Free Software Foundation, either version 3 of the
//   License, or (at your option) any later version.
//  
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Affero General Public License for more details.
//  
//   You should have received a copy of the GNU Affero General Public License
//   along with this program.  If not, see <http://www.gnu.org/licenses/>.
//  
//  

using System;
using System.IO;
using System.Web;
using System.Threading;
using System.Collections.Generic;

using Gtk;
using Glade;
using Pango;

using Anculus.Core;
using Anculus.Gui;

using Galaxium.Core;
using Galaxium.Client;
using Galaxium.Protocol;
using Galaxium.Protocol.Gui;
using Galaxium.Gui;
using Galaxium.Gui.GtkGui;

using Galaxium.Protocol.Xmpp.Library;
using Galaxium.Protocol.Xmpp.Library.Messaging;

namespace Galaxium.Protocol.Xmpp.GtkGui
{
	public class XmppConferenceWidget: BasicChatWidget
	{
		private ContactListView _contact_list;
		private XmppConference _conference;
		
		public new XmppConference Conversation {
			get { return base.Conversation as XmppConference; }
		}
		
		internal XmppConferenceWidget (IContainerWindow<Widget> window, XmppConference conf)
			:base (window, conf)
		{
			_conference = conf;
			Conversation.ContactJoined += HandleConversationContactJoined;
			Conversation.ContactLeft += HandleConversationContactLeft;
			Conversation.MessageReceived += HandleMessageReceived;
			Conversation.EventReceived += HandleMessageReceived;
			Conversation.PrivateNotify += HandlePrivateNotify;
		}

		void HandlePrivateNotify (object sender, EventArgs e)
		{
			EmitBecomeActive ();
		}
		
		void HandleMessageReceived(object sender, MessageEventArgs e)
		{
			_message_display.AddMessage (e.Message);
			EmitBecomingActive ();
		}
		
		public override void Initialize ()
		{
			base.Initialize ();
			
			HideBox (ChatWidgetPositions.RightInput);
			
			LoadContactList ();
			
			_window.Toolbar.ShowAll ();
			_entryToolbar.ShowAll ();
			
			HideBox (ChatWidgetPositions.LeftInput);
			
			base.ProcessLogs ();
		}
		
		private void LoadContactList ()
		{
			_contact_list = new XmppConferenceContactView (_conference);
			_contact_list.Manager = new XmppConferenceContactTreeManager ();
			_contact_list.RowActivated += HandleRowActivated;
			var scroll = new ScrolledWindow ();
			scroll.ShadowType = ShadowType.In;
			scroll.Add (_contact_list);
			scroll.ShowAll ();
			scroll.SetSizeRequest (200, 0);
			base.SetChatWidget (ChatWidgetPositions.RightDisplayPane, scroll);
			ShowBox (ChatWidgetPositions.RightDisplayPane);
			
			
		}
		
		protected override void BecomeReady (object sender, System.EventArgs args)
		{
			base.BecomeReady (sender, args);
		}
		
		void HandleRowActivated (object o, RowActivatedArgs args)
		{
			var data = _contact_list.GetModelData (args.Path);
			if (!(data is XmppMucContact)) return;
			var contact = data as XmppMucContact;
			Log.Debug ("Got reference to: " + contact.DisplayName);
			WindowUtility<Widget>.Activate (contact.GetConversation (), true);
		}

		public override void Destroy ()
		{
			Conversation.ContactJoined -= HandleConversationContactJoined;
			Conversation.ContactLeft -= HandleConversationContactLeft;
			Conversation.MessageReceived -= HandleMessageReceived;
			Conversation.PrivateNotify -= HandlePrivateNotify;
			_contact_list.RowActivated -= HandleRowActivated;
		}
		
		public override IEntity GetEntity (string uid, string name)
		{
			return Conversation.GetEntity (name);
		}
		
		void HandleConversationContactJoined (object sender, ContactActionEventArgs args)
		{			
			if (_conference.Connected && !(args.Contact as XmppMucContact).IsBeingReplaced) {
				var text = args.Contact.DisplayIdentifier + " has joined the conversation";
				_message_display.AddEvent (text);
			}
			
			AddEventHandlers (args.Contact as XmppMucContact);
		}
		
		void HandleConversationContactLeft (object sender, ContactActionEventArgs args)
		{
			if (_conference.Connected && !(args.Contact as XmppMucContact).IsBeingReplaced) {
				var text = args.Contact.DisplayIdentifier + " has left the conversation";
				if (!String.IsNullOrEmpty (args.Contact.DisplayMessage))
					text += " (" + args.Contact.DisplayMessage + ")";
				_message_display.AddEvent (text);
			}
			
			RemoveEventHandlers (args.Contact as XmppMucContact);
		}
		
		void AddEventHandlers (XmppMucContact contact)
		{
		//	contact.DisplayImageChange += ContactDisplayImageChanged;
		//	contact.DisplayMessageChange += ContactDisplayMessageChanged;
		//	contact.DisplayNameChange += ContactDisplayNameChanged;
		//	contact.PresenceChange += ContactPresenceChanged;
		//	contact.SupressChange += ContactSupressChanged;
		}
		
		void RemoveEventHandlers (XmppMucContact contact)
		{
		//	contact.DisplayImageChange -= ContactDisplayImageChanged;
		//	contact.DisplayMessageChange -= ContactDisplayMessageChanged;
		//	contact.DisplayNameChange -= ContactDisplayNameChanged;
		//	contact.PresenceChange -= ContactPresenceChanged;
		//	contact.SupressChange -= ContactSupressChanged;
		}

		protected override void GeneratePersonalLabel ()
		{
			base.GeneratePersonalLabel();
		}

		public override void SaveFont ()
		{
		}
		
		public override void LoadFont ()
		{
		}

		public override void SendFile (string filename)
		{
			throw new System.NotImplementedException();
		}
		
		public override void SwitchTo ()
		{
			MenuUtility.FillToolBar ("/Galaxium/Gui/XMPP/ContainerWindow/ConferenceToolbar",
			                         new DefaultExtensionContext (this),
			                         _window.Toolbar as Toolbar);
			MenuUtility.FillMenuBar ("/Galaxium/Gui/XMPP/ContainerWindow/ConferenceMenu",
			                         new DefaultExtensionContext (this),
			                         _window.Menubar as MenuBar);
		}

		public override void SwitchFrom ()
		{
		}
		
		protected override void MessageEntryTextSubmitted (object sender, SubmitTextEventArgs args)
		{
			base.MessageEntryTextSubmitted (sender, args);
			
			if (args.Text.Trim ().Length == 0) return;

		//	CancelTyping ();
			_conference.SendMessage (args.Text);
			args.Submitted = true;
				
			// The message is displayed via received event
		}
	}
}
